from flask import Flask, request, g
from flask_cors import CORS
from flasgger import Swagger

import os
import logging
from pathlib import Path
from importlib import import_module

from config import GlobalContextData
from .api_tools.catch import handle_404_error, handle_500_error
from .api_tools.log_handler import JSONLogHandler

app = Flask(__name__)

# setting logger
handler = JSONLogHandler()
handler.setLevel(logging.DEBUG)
app.logger.addHandler(handler)
if GlobalContextData.Debug:
    app.logger.setLevel(logging.DEBUG)
    print(' * Startup flask logger - DEBUG')
else:
    app.logger.setLevel(logging.INFO)
    print(' * Startup flask logger - INFO')

# swagger
if GlobalContextData.Debug:
    swagger = Swagger(app)
    print(' * Startup swagger ui: http://localhost:5000/apidocs/')

# flask cors
if GlobalContextData.CORS:
    CORS(app)

# security session
app.secret_key = os.urandom(24)

app.register_error_handler(404, handle_404_error)
app.register_error_handler(500, handle_500_error)
app.register_error_handler(Exception, handle_500_error)

@app.before_request
def before_request():
    g.log_context = {
        'method': request.method,
        'path': request.path,
        'user': None,
        'action': request.blueprint,
        'token': None,
        'payload': request.get_data().decode('utf-8'),
        'auth': request.authorization,
        'query': request.args
    }

blueprints = [x for x in Path('apis').glob('*.py')]

for blueprint in blueprints:
    try:
        module_name = f"apis.{blueprint.stem}"
        module = import_module(module_name)

        blueprint_app = getattr(module, 'app', None)

        if blueprint_app is None:
            print(f"** startup api.py - blueprint {blueprint.stem} does not have an 'app' attribute")
            continue

        CORS(blueprint_app)
        blueprint_app.register_error_handler(404, handle_404_error)
        blueprint_app.register_error_handler(500, handle_500_error)
        blueprint_app.register_error_handler(Exception, handle_500_error)

        app.register_blueprint(blueprint_app)
    except Exception as e:
        print(f"** startup api.py - blueprint {blueprint.stem} load failed: {e}")
        continue

def run():
    if GlobalContextData.Debug:
        app.run(host=GlobalContextData.Host, port=GlobalContextData.Port, debug=GlobalContextData.HotLoad)
    else:
        from waitress import serve
        serve(app, host=GlobalContextData.Host, port=GlobalContextData.Port)